/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package TimeRecording.business;

import TimeRecording.enums.AbsenceGridCell;
import TimeRecording.enums.PartOfDay;
import TimeRecording.tables.Employee;
import TimeRecording.tables.HolidayRequest;
import TimeRecording.tables.PublicHoliday;
import TimeRecording.tables.SicknessReport;
import java.util.Collection;
import java.util.Date;

/**
 *
 * @author david
 */
public class AbsenceGrid {

    private Collection<HolidayRequest> holidayRequests;
    private Collection<SicknessReport> sicknessReports;
    private Collection<PublicHoliday> publicHolidays;

    public AbsenceGrid(Collection<HolidayRequest> holidayRequests,
            Collection<SicknessReport> sicknessReports,
            Collection<PublicHoliday> publicHolidays) {

        this.holidayRequests = holidayRequests;
        this.sicknessReports = sicknessReports;
        this.publicHolidays = publicHolidays;
    }

    /**
     * Gets the part of the day given up to holiday (or null if there's no
     * holiday.
     *
     * @param employee
     * @param date
     * @return
     */
    public PartOfDay getHolidayCell(Employee employee, Date date) {
        
        PartOfDay partOfDay = null;
        
        for (HolidayRequest holidayRequest : holidayRequests) {
            
            // Wrong employee?
            if (!holidayRequest.getEmployeeId().equals(employee)) {
                continue;
            }
            
            // Holiday starts after this date?
            if (holidayRequest.getFirstDayOfHoliday().after(date)) {
                continue;
            }

            // Holiday ends before this date?
            if (holidayRequest.getLastDayOfHoliday().before(date)) {
                continue;
            }
            
            boolean dateOnBoundary = false;

            if (holidayRequest.getFirstDayOfHoliday().equals(date)) {
                partOfDay = PartOfDay.add(partOfDay,
                        holidayRequest.getFirstDayPart());
                dateOnBoundary = true;
            }

            if (holidayRequest.getLastDayOfHoliday().equals(date)) {
                partOfDay = PartOfDay.add(partOfDay,
                        holidayRequest.getLastDayPart());
                dateOnBoundary = true;
            }

            if (!dateOnBoundary) {
                partOfDay = PartOfDay.ALL_DAY;
            }
        }
        
        return partOfDay;
    }

    /**
     * Gets the part of the day given up to sickness (or null if there's no
     * sickness.
     *
     * @param employee
     * @param date
     * @return
     */
    public PartOfDay getSicknessCell(Employee employee, Date date) {

        PartOfDay partOfDay = null;

        for (SicknessReport sicknessReport : sicknessReports) {

            // Wrong employee?
            if (!sicknessReport.getEmployeeId().equals(employee)) {
                continue;
            }

            // Sickness starts after this date?
            if (sicknessReport.getFirstDayOfSickness().after(date)) {
                continue;
            }

            // Sickness ends before this date?
            if (sicknessReport.getLastDayOfSickness().before(date)) {
                continue;
            }

            boolean dateOnBoundary = false;

            if (sicknessReport.getFirstDayOfSickness().equals(date)) {
                partOfDay = PartOfDay.add(partOfDay,
                        sicknessReport.getFirstDayPart());
                dateOnBoundary = true;
            }

            if (sicknessReport.getLastDayOfSickness().equals(date)) {
                partOfDay = PartOfDay.add(partOfDay,
                        sicknessReport.getLastDayPart());
                dateOnBoundary = true;
            }

            if (!dateOnBoundary) {
                partOfDay = PartOfDay.ALL_DAY;
            }
        }

        return partOfDay;
    }

    public boolean isPublicHoliday(Date date) {

        for (PublicHoliday publicHoliday : publicHolidays) {
            if (publicHoliday.getDateOfHoliday().equals(date)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Reflects the presence of sickness of holiday for the specified date as a
     * single enumerated type.
     *
     * @param employee
     * @param date
     * @return
     */
    public AbsenceGridCell getCell(Employee employee, Date date) {

        PartOfDay holiday = getHolidayCell(employee, date);
        PartOfDay sickness = getHolidayCell(employee, date);

        // No holiday or sickness?
        if (holiday == null) {
            if (sickness == null) {
                return AbsenceGridCell.PRESENT;
            }
        }

        // No holiday; i.e. only sickness?
        if (holiday == null) {
            switch (sickness) {
                case ALL_DAY:
                    return AbsenceGridCell.SICK_ALL_DAY;
                case AM:
                    return AbsenceGridCell.SICK_AM;
                case PM:
                    return AbsenceGridCell.SICK_PM;
            }
        }

        // No sickness; i.e. only holiday?
        if (sickness == null) {
            switch (holiday) {
                case ALL_DAY:
                    return AbsenceGridCell.HOL_ALL_DAY;
                case AM:
                    return AbsenceGridCell.HOL_AM;
                case PM:
                    return AbsenceGridCell.HOL_PM;
            }
        }

        // We've got holiday and sickness!
        switch (sickness) {
            case ALL_DAY:
                return AbsenceGridCell.SICK_ALL_DAY;
            case AM:
                if (holiday != PartOfDay.AM) {
                    return AbsenceGridCell.SICK_AM_HOL_PM;
                } else {
                    return AbsenceGridCell.SICK_AM;
                }
            case PM:
                if (holiday != PartOfDay.PM) {
                    return AbsenceGridCell.HOL_AM_SICK_PM;
                } else {
                    return AbsenceGridCell.SICK_AM;
                }
        }

        return AbsenceGridCell.PRESENT;
    }
}
